package com.axeiya.cheddargetter;

import java.io.IOException;
import java.io.StringReader;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;



import com.axeiya.cheddargetter.exceptions.BadGatewayException;
import com.axeiya.cheddargetter.exceptions.BadRequestException;
import com.axeiya.cheddargetter.exceptions.NotAuthorizedException;
import com.axeiya.cheddargetter.exceptions.PreconditionFailedException;
import com.axeiya.cheddargetter.exceptions.UnprocessableEntityException;
import com.axeiya.cheddargetter.exceptions.InternalServerErrorException;
import com.axeiya.cheddargetter.exceptions.NotFoundException;

public class CheddarGetterClient {

	private static HttpClient client;
	public static String contentType = "application/xml";
	public static String charset = "UTF-8";

	public static void createInstance(String userName, String password) {

		HostConfiguration hostConfig = new HostConfiguration();
		hostConfig.setHost("cheddargetter.com", 443, Protocol.getProtocol("https"));
		
		client = new HttpClient();
		client.getParams().setAuthenticationPreemptive( true);
		client.getState().setCredentials( new AuthScope( "cheddargetter.com", 443, "CheddarGetter API"), new UsernamePasswordCredentials(userName, password));
		client.setHostConfiguration( hostConfig);

	}
	
	public static HttpClient getClient() {
		return client;
	}


	public static void handleResponseCode(HttpMethodBase response){
		switch (response.getStatusLine().getStatusCode()) {
		case 400:
		case 401:
		case 404:
		case 412:
		case 422:
		case 500:
		case 522:
			Element errors = parseResponse(response);
			ArrayList<Error> errorsList = new ArrayList<Error>();
			try {
				Element errorsElement = (Element) XPath.selectSingleNode(errors, "//error");
				parseError(errorsElement, response.getStatusLine().getStatusCode());
			} catch (JDOMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		default:
			break;
		}

	}



	private static void parseError(Element errorsElement, int type) {
		switch (type) {
		case 400:
			throw new BadRequestException(errorsElement.getText());
		case 401:
			throw new NotAuthorizedException(errorsElement.getText());
		case 404:
			throw new NotFoundException(errorsElement.getText());
		case 412:
			throw new PreconditionFailedException(errorsElement.getText() + " "
					+ errorsElement.getAttributeValue("auxCode"));
		case 422:
			throw new UnprocessableEntityException(errorsElement.getText() + " "
					+ errorsElement.getAttributeValue("auxCode"));
		case 500:
			throw new InternalServerErrorException();
		case 502:
			throw new BadGatewayException();
		}

	}

	public static Element parseResponse(HttpMethodBase response) {
		try {
			SAXBuilder builder = new SAXBuilder();
			String responseString = response.getResponseBodyAsString();
			System.out.println(responseString);
			try {
				Document doc = builder.build(new StringReader(responseString));
				return doc.getRootElement();
			} catch (JDOMException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	

	public static Element execute(HttpMethodBase method) {
		try {
			client.executeMethod(method);	
			handleResponseCode(method);
			return parseResponse(method);
		} catch (HttpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}

}
